home *** CD-ROM | disk | FTP | other *** search
- /* file strftime.c */
-
- /*
- routine to convert a time structure into a formatted string
- based on the standard ANSI C function as described in K & R 2nd ed.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <dos.h>
- #include <assert.h>
-
- #include "strftime.h"
-
- static void putcode(char *str, int i1, int i2, int i3, char sep);
- static void showtim(char *str, const struct tm *nows);
- static void strdd(char *str, int num);
- static void showdate(char *str, const struct tm *tp);
-
- static int country_flag = 0;
- static struct country rec;
-
- static char *weekdays[] =
- {
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday"
- };
-
- static char *months[] =
- {
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- };
-
- size_t strftime(char *s, size_t smax, const char *fmt, const struct tm *tp)
- {
- size_t retlen = 0;
- char str[80];
- int l;
-
- if (country_flag == 0)
- {
- country_flag = 1;
- assert(country(0, &rec) != NULL);
- }
-
- while (*fmt)
- {
- if (*fmt != '%')
- {
- str[0] = *fmt++;
- str[1] = '\0';
- }
- else
- {
- fmt++;
- switch (*fmt++)
- {
- case 'c': /* local time and date representation */
- assert(rec.co_date >= 0 && rec.co_date < 3);
- switch(rec.co_date)
- {
- case 0: /* h m s m d y */
- showtim(str, tp);
- strcat(str, " ");
- showdate(&str[strlen(str)], tp);
- break;
- case 1: /* h m s d m y */
- showtim(str, tp);
- strcat(str, " ");
- showdate(&str[strlen(str)], tp);
- break;
- case 2: /* y m d h m s */
- showdate(str, tp);
- strcat(str, " ");
- showtim(&str[strlen(str)], tp);
- break;
- }
- break;
- case 'x': /* local date representation */
- showdate(str, tp);
- break;
- case 'X': /* local time representation */
- showtim(str, tp);
- break;
-
- case 'y': /* year without century (00-99) */
- strdd(str, tp->tm_year);
- break;
- case 'Y': /* year with century */
- sprintf(str, "%04d", tp->tm_year + 1900);
- break;
- case 'b': /* abbreviated month name */
- strncpy(str, months[tp->tm_mon], 3);
- str[3] = '\0';
- break;
- case 'B': /* full month name */
- strcpy(str, months[tp->tm_mon]);
- break;
- case 'm': /* month (01-12) */
- strdd(str, tp->tm_mon + 1);
- break;
- case 'd': /* day of the month (01-31) */
- strdd(str, tp->tm_mday);
- break;
- case 'H': /* hour (24-hour clock) (00-23) */
- strdd(str, tp->tm_hour);
- break;
- case 'I': /* hour (12-hour clock) (01-12) */
- strdd(str, (tp->tm_hour + 11) % 12 + 1);
- break;
- case 'p': /* local equivalent of AM or PM */
- strcpy(str, tp->tm_hour < 12 ? "AM" : "PM");
- break;
- case 'M': /* minute (00-59) */
- strdd(str, tp->tm_min);
- break;
- case 'S': /* second (00-59) */
- strdd(str, tp->tm_sec);
- break;
- case 'a': /* abbreviated weekday name. */
- strncpy(str, weekdays[tp->tm_wday], 3);
- str[3] = '\0';
- break;
- case 'A': /* full weekday name */
- strcpy(str, weekdays[tp->tm_wday]);
- break;
- case 'w': /* weekday (0 - 6, Sunday is 0) */
- sprintf(str, "%d", tp->tm_wday);
- break;
- case 'j': /* day of the year (001-366) */
- sprintf(str, "%03d", tp->tm_yday + 1);
- break;
- case 'U':
- /*
- week number of the year (Sunday as 1st day of week)
- (01-53)
- */
- strdd(str, (tp->tm_yday + 13 - tp->tm_wday) / 7);
- break;
- case 'W':
- /*
- week number of the year (Monday as 1st day of week)
- (01-53)
- */
- strdd(str, (tp->tm_yday + (7 - tp->tm_wday) % 7) / 7 + 1);
- break;
- case 'Z': /* time zone, if any */
- strncpy(str, tzname[daylight], 3);
- str[3] = '\0';
- break;
- case '%':
- str[0] = '%';
- str[1] = '\0';
- break;
- default: /* ignore it */
- str[0] = '\0';
- }
- }
- l = strlen(str);
- retlen += l;
- if (retlen > smax) return 0;
- strncpy(s, str, l);
- s += l;
- }
- retlen++;
- if (retlen > smax) return 0;
- *s = '\0';
- return retlen;
- }
-
- static void showtim(char *str, const struct tm *nows)
- {
- int hrs, min, sec, hour12;
-
- hrs = nows->tm_hour;
- assert(hrs >= 0 && hrs < 24);
- min = nows->tm_min;
- assert(min >= 0 && min < 60);
- sec = nows->tm_sec;
- assert(sec >= 0 && sec < 60);
- assert(rec.co_time == 0 || rec.co_time == 1);
- switch(rec.co_time)
- {
- case 0: /* 12 hour clock */
- hour12 = hrs % 12;
- putcode(str,
- (hour12 == 0) ? 12 : hour12, min, sec, rec.co_tmsep[0]);
- strcat(str, hrs < 12 ? "AM" : "PM");
- break;
- case 1: /* 24 hour clock */
- putcode(str, hrs, min, sec, rec.co_tmsep[0]);
- break;
- }
- }
-
- static void showdate(char *str, const struct tm *tp)
- {
- assert(rec.co_date >= 0 && rec.co_date < 3);
- switch(rec.co_date)
- {
- case 0: /* m d y */
- putcode
- (
- str,
- tp->tm_mon + 1,
- tp->tm_mday,
- tp->tm_year,
- rec.co_dtsep[0]
- );
- break;
- case 1: /* d m y */
- putcode
- (
- str,
- tp->tm_mday,
- tp->tm_mon + 1,
- tp->tm_year,
- rec.co_dtsep[0]
- );
- break;
- case 2: /* y m d */
- putcode
- (
- str,
- tp->tm_year,
- tp->tm_mon + 1,
- tp->tm_mday,
- rec.co_dtsep[0]
- );
- break;
- }
- }
-
- static void putcode(char *str, int i1, int i2, int i3, char sep)
- {
- assert(i1 >= 0);
- assert(i1 <= 99);
- assert(i2 >= 0);
- assert(i2 <= 99);
- assert(i3 >= 0);
- assert(i3 <= 99);
- strdd(str, i1);
- str[2] = sep;
- strdd(&str[3], i2);
- str[5] = sep;
- strdd(&str[6], i3);
- }
-
- static void strdd(char *str, int num)
- {
- str[0] = num / 10 + '0';
- str[1] = num % 10 + '0';
- str[2] = '\0';
- }
-
- /* end of file strftime.c */
-